﻿using Nemerle;
using Nemerle.Assertions;
using Nemerle.Collections;
using Nemerle.Text;
using Nemerle.Utility;

using System;
using System.Collections.Generic;
using System.Linq;
using Nemerle2.Compiler;
using Microsoft.Cci;
using System.Diagnostics;

namespace MetadataReader.CCI
{
  abstract class CciMemberInfo : NMemberInfo
  {
    protected this([NotNull] declType : CciTypeInfo, [NotNull] definition : ITypeDefinitionMember, index : int)
    {
      Definition       = definition;
      DeclaringCciType = declType;

      def typeBits     = declType.UniqueKey << 16; // A declType.UniqueKey can has big value. Put it to high bits.
      def memberBits   = index + 1L;
      assert(typeBits & memberBits == 0);
      UniqueKey        =  typeBits | memberBits;
    }

    public override UniqueKey : long { get; }

    public sealed override CustomAttributes : ICustomAttributes
    {
      [Memoize] get { CciCustomAttributes(Provider, Definition.Attributes) }
    }

    public override IsObsolete : bool
    {
      get { Definition.Attributes.HasAttribute(Constants.ObsoleteAttributeFullName) }
    }

    /// <summary>Type definition member</summary>
    protected Definition : ITypeDefinitionMember { get; }

    /// <summary>Metadata provider</summary>
    protected Provider : CciMetadataProvider { get { DeclaringCciType.Provider } }

    public sealed override IsInternal : bool
    {
      get
      {
        def vis = Definition.Visibility;
        vis == TypeMemberVisibility.Assembly || vis == TypeMemberVisibility.FamilyAndAssembly
      }
    }

    public sealed override Name : string { get { Definition.Name.Value } }

    public sealed override DeclaringType : ITypeInfo { get { DeclaringCciType } }

    internal DeclaringCciType : CciTypeInfo { get; }

    public sealed override IsPublic : bool
    {
      get { Definition.Visibility == TypeMemberVisibility.Public }
    }

    public sealed override IsPrivate : bool
    {
      get { Definition.Visibility == TypeMemberVisibility.Private }
    }

    public sealed override IsProtected : bool
    {
      get { Definition.Visibility == TypeMemberVisibility.Family }
    }
  }
}
